/**
 * @description: 网格名称处理
 * @file: mesh-name.ts
 * @author: Evan
 * @date: 2025.07.17 15:07:13
 * @week: 周四
 * @version: V
 */

import { Message } from '@/utils/element'
import { Scene } from '../class'
import * as MD from '../data/methods'
const { THREE, Hooks } = MD

const { setMetalnessMaterial, setGlassMaterial } = Hooks.useMaterial()

type ST = InstanceType<typeof Scene>

export function meshName(core: ST) {
  // 金属配置
  const metalOpts = {
    check: false,
    checkName: '金属',
    metalness: 0.5,
    roughness: 0
  }

  // 玻璃配置
  const glassOpts = {
    check: false,
    checkName: '玻璃',
    roughness: 0, // 玻璃表面光滑
    envMapIntensity: 1, //环境贴图对Mesh表面影响程度
    transmission: 1, //透射度(透光率)
    ior: 2.1, //折射率
    metalness: 0 // 玻璃非金属  金属度设置0
  }

  // 线框配置
  const lineOpts = {
    blurring: false,
    blurringName: '线框',
    wireframe: false,
    color: 0x00e0ff,
    opacity: 0.5,
    all: false
  }

  return {
    add() {
      const gui = core.gui
      const waterOpts = {
        waterName: '水面',
        water: () => {
          this.addWater(waterOpts.waterName)
        }
      }
      const group = gui.addFolder('名称包含处理')
      {
        group.add(waterOpts, 'waterName').name('水面网格名称')
        group.add(waterOpts, 'water').name('生成水面')
      }

      {
        group
          .add(metalOpts, 'check')
          .name('金属材质')
          .onChange(e => {
            metalOpts.metalness = e ? 0.5 : 0
            metalOpts.roughness = e ? 0 : 0.5
            this.metalnessMaterialUpdate()
          })
        group.add(metalOpts, 'checkName').name('金属网格名称')
        group
          .add(metalOpts, 'metalness', 0, 1)
          .name('金属权重')
          .onChange(() => {
            this.metalnessMaterialUpdate()
          })
        group
          .add(metalOpts, 'roughness', 0, 1)
          .name('金属粗糙度')
          .onChange(() => {
            this.metalnessMaterialUpdate()
          })

        group
          .add(glassOpts, 'check')
          .name('玻璃材质')
          .onChange(e => {
            glassOpts.roughness = e ? 0 : 0.5
            glassOpts.envMapIntensity = e ? 1 : 0
            glassOpts.transmission = e ? 1 : 0
            glassOpts.ior = e ? 2.1 : 1.5
            this.glassMaterialUpdate()
          })
        group.add(glassOpts, 'checkName').name('玻璃网格名称')
        group
          .add(glassOpts, 'roughness', 0, 1)
          .name('玻璃光滑度')
          .onChange(() => {
            this.glassMaterialUpdate()
          })
        group
          .add(glassOpts, 'envMapIntensity', 0, 1)
          .name('玻璃环境贴图影响权重')
          .onChange(() => {
            this.glassMaterialUpdate()
          })
        group
          .add(glassOpts, 'transmission', 0, 1)
          .name('玻璃透射度(透光率)')
          .onChange(() => {
            this.glassMaterialUpdate()
          })
        group
          .add(glassOpts, 'ior', 0, 10)
          .name('玻璃折射率')
          .onChange(() => {
            this.glassMaterialUpdate()
          })
      }

      {
        group
          .add(lineOpts, 'blurring')
          .name('虚化材质')
          .onChange(() => {
            this.blurringMaterialUpdate()
          })
        group.add(lineOpts, 'blurringName').name('虚化网格名称')
        group
          .add(lineOpts, 'all')
          .name('全部虚化')
          .onChange(() => {
            this.blurringMaterialUpdate()
          })
        group
          .addColor(lineOpts, 'color')
          .name('虚化颜色')
          .onChange(() => {
            this.blurringMaterialUpdate()
          })
        group
          .add(lineOpts, 'opacity', 0, 1)
          .name('虚化透明度')
          .onChange(() => {
            this.blurringMaterialUpdate()
          })
        group
          .add(lineOpts, 'wireframe')
          .name('虚化线框')
          .onChange(() => {
            this.blurringMaterialUpdate()
          })
      }

      group.close()
    },

    // 添加水面
    addWater(waterName: string) {
      const obj = core.scene.getObjectByName(waterName)
      if (!obj) {
        Message('未找到网格！', 'error')
        return
      }
      const water = MD.createWater(obj as MD.THREE.Mesh)

      // 获取世界坐标
      water.position.copy(obj.getWorldPosition(new THREE.Vector3()))
      // 转换世界旋转角度
      const worldMatrix = obj.matrixWorld
      const position = new THREE.Vector3()
      const quaternion = new THREE.Quaternion()
      const scale = new THREE.Vector3()
      worldMatrix.decompose(position, quaternion, scale)
      const euler = new THREE.Euler().setFromQuaternion(quaternion)
      water.rotation.copy(euler)
      // 转换世界缩放大小
      water.scale.copy(obj.getWorldScale(new THREE.Vector3()))

      obj.position.y -= 0.2
      if (core.water) {
        core.scene.remove(core.water)
      }

      core.water = water
      core.addObject(core.water)
    },

    // 金属材质更新
    metalnessMaterialUpdate() {
      const { metalness, roughness, checkName } = metalOpts
      const reg = new RegExp(`(${checkName})`)
      core.modelGroup?.children.forEach((model: any) => {
        model.traverse((el: MD.THREE.Mesh) => {
          // 检索指定名称或者 无子级
          if (reg.test(el.name) || model.children.length == 0) {
            if (Array.isArray(el.material)) {
              el.material = el.material.map(mat => {
                return setMetalnessMaterial(mat, metalness, roughness)
              })
            } else {
              const mat = el.material
              el.material = setMetalnessMaterial(mat, metalness, roughness)
            }
          }
        })
      })
    },

    // 玻璃材质更新
    glassMaterialUpdate() {
      const reg = new RegExp(`(${glassOpts.checkName})`)
      core.modelGroup?.children.forEach((model: MD.THREE.Object3D) => {
        model.traverse((el: AnyObject) => {
          // 检索指定名称或者 无子级
          if (reg.test(el.name) || model.children.length == 0) {
            if (Array.isArray(el.material)) {
              el.material = el.material.map((mat: MD.THREE.Mesh) => {
                return setGlassMaterial(mat, glassOpts)
              })
            } else {
              const mat = el.material
              el.material = setGlassMaterial(mat, glassOpts)
            }
          }
        })
      })
    },

    // 线框材质更新
    blurringMaterialUpdate() {
      const reg = new RegExp(`(${lineOpts.blurringName})`)
      core.modelGroup?.children.forEach(model => {
        model.traverse((el: AnyObject) => {
          // 检索指定名称或者 无子级
          if (lineOpts.all || model.children.length == 0 || reg.test(el.name)) {
            if (el.isMesh) {
              if (lineOpts.blurring || lineOpts.all) {
                if (!el.__material__) {
                  el.__material__ = el.material
                }
                el.material = new THREE.MeshBasicMaterial({
                  color: lineOpts.color,
                  wireframe: lineOpts.wireframe,
                  transparent: true,
                  opacity: lineOpts.opacity
                })
              } else {
                if (el.__material__) {
                  el.material = el.__material__
                }
              }
            }
          } else {
            if (el.isMesh && el.__material__) {
              el.material = el.__material__
            }
          }
        })
      })
    }
  }
}
